package net.jcip.examples.chapter6.thread.ThreadPool;

import java.util.Random;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 通用线程池管理器（推荐模板）
 * 包含线程池创建、任务提交与优雅关闭逻辑。
 */
public class ThreadPoolManager {

    // 1️⃣ 创建一个可配置的线程池
    private static final ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(
            4,                      // corePoolSize: 核心线程数
            8,                      // maximumPoolSize: 最大线程数
            60L, TimeUnit.SECONDS,  // keepAliveTime: 非核心线程空闲超时
            new LinkedBlockingQueue<>(100), // 有界队列防止OOM
            new NamedThreadFactory("biz-worker"), // 自定义线程工厂
            new ThreadPoolExecutor.AbortPolicy()  // 拒绝策略：抛出异常
    );

    // 自定义线程工厂（便于排查日志和监控）
    static class NamedThreadFactory implements ThreadFactory {
        private final AtomicInteger counter = new AtomicInteger(1);
        private final String prefix;

        public NamedThreadFactory(String prefix) {
            this.prefix = prefix;
        }

        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(r);
            t.setName(prefix + "-" + counter.getAndIncrement());
            // 设为非守护线程，确保任务执行完毕后再退出
            t.setDaemon(false);
            return t;
        }
    }

    // 2️⃣ 提交任务示例
    public static void submitTask(Runnable task) {
        EXECUTOR.submit(task);
    }

    // 3️⃣ 优雅关闭线程池
    public static void shutdown() {
        EXECUTOR.shutdown(); // 禁止提交新任务，但会执行完已提交任务
        try {
            // 等待最多 3 秒让任务执行完毕     等待线程池中所有任务执行完毕或超时/中断。
            //	1.	检测线程池是否已关闭（必须先 shutdown() 或 shutdownNow()）；
            //	2.	阻塞当前线程（通常是主线程）；
            //	3.	直到以下任一条件发生时返回：
            //	•	✅ 所有任务都执行完；
            //	•	🕒 超过等待时间；
            //	•	❌ 当前线程被中断。
            if (!EXECUTOR.awaitTermination(10, TimeUnit.SECONDS)) {
                System.out.println("等待超时，尝试强制关闭线程池...");
                EXECUTOR.shutdownNow(); // 立即中断所有正在执行的任务
            }
        } catch (InterruptedException e) {
            System.out.println("关闭线程池被中断，强制关闭");
            EXECUTOR.shutdownNow();
            Thread.currentThread().interrupt();
        }
        System.out.println("线程池已关闭！");
    }

    // 4️⃣ 示例主函数
    public static void main(String[] args) {
        // 提交10个任务
        for (int i = 0; i < 10; i++) {
            int taskId = i;
            submitTask(() -> {
                Random random = new Random();
                int consumingTime = random.nextInt(5);
                long startTime = System.nanoTime();
                System.out.println(Thread.currentThread().getName() + " 执行任务 " + taskId + "任务耗时:" + consumingTime);
                try {
                    Thread.sleep(consumingTime * 1000L);
                } catch (InterruptedException e) {
                    long endTime = System.nanoTime();
                    System.out.println(Thread.currentThread().getName() + " 被中断！" + "任务耗时:" + consumingTime + "任务执行时间：" + TimeUnit.SECONDS.convert((endTime - startTime), TimeUnit.NANOSECONDS));
                    Thread.currentThread().interrupt();
                }
            });
        }

        //调用线程池  shutdown
        shutdown();

        // 模拟主线程执行其他逻辑
        System.out.println("主线程执行中...");
    }
}
